import * as THREE from 'three';
import * as Painter from './Painter.js';
import { Lut } from 'three/examples/jsm/math/Lut.js';


class Sprite {
    constructor(name) {
        this.name = name;
        // this.canvas = document.createElement('canvas');
        // this.ctx = this.canvas.getContext('2d');
        this.lut = new Lut();
    }

    getStrWidth(ctx, str) {
        let w = 0;
        for (let c of str) {
            w += ctx.measureText(c).width;
        }
        return w;
    }

    // Blackboard Flip Y author by ouyang
    mirrorBlackboard(canvasUrl) {
        // console.log('mirrorBlackboard', canvasUrl);
        let width = canvasUrl.width;
        let height = canvasUrl.height;
        let newCanvas = document.createElement('canvas');
        newCanvas.width = width;
        newCanvas.height = height;

        let newCtx = newCanvas.getContext('2d');
        newCtx.scale(1, -1);
        newCtx.translate(0, -height);
        newCtx.drawImage(canvasUrl, 0, 0);
        // let flipImage = newCtx.getImageData(0, 0, width, height);
        // return flipImage;
        let flipImage = newCanvas.toDataURL('image/jpg');
        return flipImage;
    }

    // create Tips fixed Blackboard author by ouyang
    createBlackboard(text, size, baseWidth) {
        const borderSize = 6;
        let canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const font = `${size}px bold`;
        ctx.font = font;
        const textWidth = this.getStrWidth(ctx, text);

        // (592x324) to (512x256).
        const doubleBorderSize = borderSize * 2;
        const width = baseWidth + doubleBorderSize + 436;
        const height = size + doubleBorderSize + 212;
        ctx.canvas.width = width;
        ctx.canvas.height = height;

        ctx.font = font;
        ctx.textBaseline = 'middle';
        ctx.textAlign = 'left';

        ctx.fillStyle = '#a8a8a8';
        Painter.drawRoundRect(ctx, 0, 0, width, height, 10);
        ctx.fill();

        const scaleFactor = Math.min(1, width / textWidth);
        ctx.translate(30, 30);
        ctx.fillStyle = '#000';

        let txtArr = text.split('\r\n');
        ctx.fillText(txtArr[0], 0, 0);
        ctx.fillText(txtArr[1], 0, 50);
        ctx.fillText(txtArr[2], 0, 100);
        ctx.fillText(txtArr[3], 0, 150);
        ctx.fillText(txtArr[4], 0, 200);
        ctx.fillText(txtArr[5], 0, 250);

        return ctx.canvas;
    }
    getBlackboardMesh(parentId, txt) {
        let geometry = new THREE.PlaneGeometry(30, 30);
        let mirrorBlackboard = this.mirrorBlackboard(this.createBlackboard(txt, 32, 64));
        let texture = THREE.ImageUtils.loadTexture(mirrorBlackboard);
        let material = new THREE.MeshBasicMaterial({
            map: texture,
            side: THREE.DoubleSide,
            opacity: 1,
            transparent: true
        });
        let mesh = new THREE.Mesh(geometry, material);
        console.log('Sprite.getBlackboardMesh: mesh', mesh);
        mesh.scale.set(0.1, 0.1, 0.1);
        mesh.parentId = parentId;
        return mesh;
    }

    // create Tips Facing the camera author by ouyang
    createTips(text, size = 32, baseWidth = 64) {
        const borderSize = 6;
        const ctx = document.createElement('canvas').getContext('2d');

        const font = `${size}px bold`;
        ctx.font = font;

        let that = this;
        let maxTxtWidth = 0;
        let txtArr = text.split('\r\n');
        // console.error('Sprite.createTips: txtArr', txtArr);

        // txtArr.forEach((v, i) => {
        //     let strWidth = this.getStrWidth(ctx, v);
        //     if (i === 0) {
        //         maxTxtWidth = strWidth;
        //     } else {
        //         if (maxTxtWidth <= strWidth) {
        //             maxTxtWidth = strWidth;
        //         }
        //     }
        // });

        const textWidth = that.getStrWidth(ctx, text);
        // console.error('Sprite.createTips: textWidth', textWidth);
        const doubleBorderSize = borderSize * 2;

        // 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048
        // (592x324) to (512x256).
        // const width = textWidth + doubleBorderSize;
        const width = baseWidth + doubleBorderSize + 436;
        const height = size + doubleBorderSize + 212;
        ctx.canvas.width = width;
        ctx.canvas.height = height;

        // need to set font again after resizing canvas
        ctx.font = font;
        ctx.textBaseline = 'middle';
        ctx.textAlign = 'left';

        ctx.fillStyle = '#a8a8a8';
        // ctx.fillRect(0, 0, width, height);
        Painter.drawRoundRect(ctx, 0, 0, width, height, 10);
        ctx.fill();

        // scale to fit but don't stretch
        const scaleFactor = Math.min(1, width / textWidth);
        ctx.translate(30, 30);
        // ctx.scale(scaleFactor, scaleFactor);
        ctx.fillStyle = '#000';

        ctx.fillText(txtArr[0], 0, 0);
        ctx.fillText(txtArr[1], 0, 50);
        ctx.fillText(txtArr[2], 0, 100);
        ctx.fillText(txtArr[3], 0, 150);
        ctx.fillText(txtArr[4], 0, 200);
        ctx.fillText(txtArr[5], 0, 250);

        return ctx.canvas;
    }
    getTipsTextSprite(parentId, txt) {
        let canvas = this.createTips(txt, 32, 64);
        let texture = new THREE.Texture(canvas);

        texture.needsUpdate = true;

        let spriteMaterial = new THREE.PointsMaterial({ map: texture, sizeAttenuation: true, size: 6 });
        let geometry = new THREE.BufferGeometry();
        let vertices = [0, 0, 0];

        geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
        let sprite = new THREE.Points(geometry, spriteMaterial);
        sprite.parentId = parentId;
        return sprite;
    }

    // create Sprite
    createCanvas(text, size) {
        const ctx = document.createElement('canvas').getContext('2d');
        const font = `${size}px bold`;

        // set font
        ctx.font = font;

        const textWidth = this.getStrWidth(ctx, text); // (72x44) to (64x32).
        const cw = textWidth * 1.2;
        const ch = textWidth;
        const scaleFactor = Math.min(1, textWidth / (size * 3));
        // console.error(`${text} ---> ${scaleFactor} ( ${textWidth}, ${size * 3} )`);

        ctx.canvas.width = cw;
        ctx.canvas.height = ch;

        // need to set font again after resizing canvas
        ctx.font = font;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#47484c';
        ctx.fillRect(0, 0, cw, ch);
        // Painter.drawRoundRect(ctx, 0, 0, cw, ch, 10);
        ctx.fill();

        // scale to fit but don't stretch
        ctx.translate(cw / 2, ch / 2);
        ctx.scale(scaleFactor, scaleFactor * 0.8);
        ctx.fillStyle = '#f2f2f4';
        ctx.fillText(text, 0, 0);

        return ctx.canvas;
    }
    getTextSprite(txt) {
        // let canvas = document.createElement('canvas');
        // let ctx = canvas.getContext('2d');
        // let fs = 100,
        //     w = this.getStrWidth(ctx, txt) * 10,
        //     h = fs;
        // console.log('======> ', txt, w, h);
        // canvas.setAttribute('width', w);
        // canvas.setAttribute('height', h);
        // // this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

        // // let canvas = this.lut.createCanvas();
        // let canvas = document.createElement('canvas');
        // let ctx = canvas.getContext('2d');
        // // ctx.font = `100px Arial`;
        // // ctx.fillStyle = 'rgba(0, 0, 0, 1.0)';
        // ctx.fillText(txt, 0, 20);

        let canvas = this.createCanvas(txt, 36);

        let texture = new THREE.Texture(canvas);
        // let texture = new THREE.CanvasTexture(canvas);
        texture.needsUpdate = true;
        let spriteMaterial = new THREE.SpriteMaterial({ map: texture }); // , transparent: false
        let sprite = new THREE.Sprite(spriteMaterial);
        // sprite.scale.x = 20;
        // sprite.scale.y = 20;
        return sprite;
    }
}

export default Sprite;
